#include "NetworkClient.h"
#include "RtsConnection.h"
#include "../shared/macros.h"
#include "../shared/logger.h"
#include "../shared/utils.h"

namespace Putin{

NetworkClient::NetworkClient(void)
{
	mState = DISCONNECTED;
	mConnection = NULL;
	mStart = false;
}

NetworkClient::~NetworkClient(void)
{
	//SAFE_DELETE(mConnection);
}

bool NetworkClient::connect( std::string ip )
{
	mConnection = new RtsConnection();
	mConnection->addOnConnectHandler(new NetFunctor<NetworkClient>(&NetworkClient::handleConnect,this));
	mConnection->addOnDisconnectedHandler(new NetFunctor<NetworkClient>(&NetworkClient::handleDisconnect,this));
	mConnection->addHandler(new NetFunctor<NetworkClient>(&NetworkClient::handlePacket,this));

	mConnection->startClient(TNL::Address(ip.c_str()));
	return mConnection->isEstablished();
}

void NetworkClient::disconnect()
{
	mConnection->disconnect("quit");
	mState = DISCONNECTED;
}

void NetworkClient::send(NetworkPacket* pack)
{
	mConnection->send2Server(pack);
}

void NetworkClient::handlePacket(NetworkConnection* net,NetworkPacket* np)
{
	if( np->getType() == NetworkPacket::npCommand)
	{
		handleCommand(net,static_cast<NetworkCommand*>(np));
	}
	else if( np->getType() == NetworkPacket::npText)
	{
		handleText(net, static_cast<NetworkText*>(np));
	}
	else
	{
		Logger::instance().loggLine("NetworkClient: Unidentified packet");
	}
}

void NetworkClient::handleConnect(NetworkConnection* net, NetworkPacket* np)
{
	// Connected to a server
	Logger::instance().loggLine("Connected to server @ " + net->getRemoteAddress());
	mState = WAITING_GO;
}

void NetworkClient::handleDisconnect(NetworkConnection* net, NetworkPacket* np)
{
	// disconnected
	Logger::instance().loggLine("Disconnected from server @ " + net->getRemoteAddress());
	mState = DISCONNECTED;
}


void NetworkClient::update()
{

	mConnection->checkMessages();

}

NetworkClient::CommandQueue& NetworkClient::getCommands()
{
	return mCommands;
}

NetworkClient::TextList& NetworkClient::getTexts()
{
	return mTexts;
}

void NetworkClient::handleCommand(Putin::NetworkConnection *net, Putin::NetworkCommand *nc)
{
	Logger::instance().loggLine("Got msg with id: " + Utils::intToString(nc->command));
	if( mState == WAITING_GO)
	{
		// simply wait for the NC_GO message. then start the game
		if( nc->command == NC_GO )
		{
			mState = RUNNING;
			mStart = true;
		}
		// Another player joined?
		else if( nc->command == NC_PLAYER) 
		{
			Logger::instance().loggLine("A player has joined with id: " + Utils::intToString(nc->id1));
		}
		// Got ourself a new ID? 
		else if( nc->command == NC_PLAYER_R)  
		{
			
		}
	}
	else if( mState == RUNNING)
	{
		// simply push the command to a waiting queue
		mCommands.push(*nc);
	}
}

void NetworkClient::handleText(Putin::NetworkConnection *net, Putin::NetworkText *nc)
{
	Logger::instance().loggLine("NetworkClient: Incomming text: [" + nc->text + "]");
}

void NetworkClient::updateKeyFrame(int frameCount)
{
	 // Psuedo kod
	// Check this key frame is the same as the command list.
	// Get all commands .. followed by some "DONE" msg
	// get possible chat messages
	// push commands to some list
	// Done.
}

} // End namespace putin